package com.acceptable.qucun.generic.security;

import com.acceptable.qucun.file.mapper.FileShareMapper;
import com.acceptable.qucun.file.service.FileShareService;
import com.acceptable.qucun.file.service.TemplateFileService;
import com.acceptable.qucun.generic.entity.RedisItem;
import com.acceptable.qucun.generic.exception.GenericExcetion;
import com.acceptable.qucun.generic.util.CodeUtil;
import com.acceptable.qucun.generic.util.result.ResultUtil;
import com.acceptable.qucun.generic.util.result.error.GenericErrorResult;
import com.acceptable.qucun.user.entity.User;
import com.acceptable.qucun.user.mapper.UserMapper;
import com.acceptable.qucun.user.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import org.springframework.stereotype.Component;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.List;
import java.util.Map;

@Component
public class LoginAuthenFilter extends AbstractAuthenticationProcessingFilter {

    @Autowired private UserService userService;
    @Autowired private RedisItem redisItem;
    @Autowired private UserMapper userMapper;
    @Autowired private TemplateFileService fileService;

    public LoginAuthenFilter(LoginAuthenManager authenManager,
                             AuthenSuccessHandler successHandler,
                             AuthenFailureHandler failureHandler) {
        super(new AntPathRequestMatcher("/user/login", "POST"));
        this.setAuthenticationManager(authenManager);
        this.setAuthenticationSuccessHandler(successHandler);
        this.setAuthenticationFailureHandler(failureHandler);
    }

    @Override
    public Authentication attemptAuthentication(HttpServletRequest request,
                                                HttpServletResponse response)
            throws AuthenticationException, IOException, ServletException {
        Map<String, String> dataMap = (Map<String, String>) request.getAttribute("data_map");

        // 传来的json 获取数据
        String loginMethod = dataMap.get("method");
        String email = dataMap.get("email");
        String value = dataMap.get("password");

        // 默认是密码登录
        UsernamePasswordAuthenticationToken token = null;
        Authentication res = null;
        if("password".equals(loginMethod)){
            token = new UsernamePasswordAuthenticationToken(email, value, null);
            res = this.getAuthenticationManager().authenticate(token);
        }

        User user = userMapper.selectByEmail(email);
        // 验证码登录
        if("verify_code".equals(loginMethod)){
            value = dataMap.get("verify_code");
            Map<String, String> redisMap = (Map<String, String>) CodeUtil.string2Object(dataMap.get("redis_map"));

            if(redisMap == null){
                throw new GenericExcetion(GenericErrorResult.VERIFY_CODE_NOT_EXIST_ERROR);
            }

            String redisVerifyCode = redisMap.get("verify_code");
            String usage = dataMap.get("usage");
            if (!usage.equals(redisMap.get("usage")) || !usage.equals(redisItem.getUsageLogin()))
                throw new GenericExcetion(GenericErrorResult.DATA_USAGE_ERROR);

            if(redisVerifyCode.equals(value)){
                List<GrantedAuthority> authorityList = AuthorityUtils.commaSeparatedStringToAuthorityList("admin");
                String password = new BCryptPasswordEncoder().encode(user.getPassword());
                res =  new UsernamePasswordAuthenticationToken(email, password, authorityList);
            } else{
                response.getWriter().write(ResultUtil.error(GenericErrorResult.VERIFY_CODE_NOT_EXIST_ERROR));
            }
        }

        if(res != null){
            Object userInfo = userService.getInitUserInfo(user.getUserId()).get("user_info");
            request.setAttribute("user_info", userInfo);
            // 是否记住登录状态
            request.setAttribute("remember_me", dataMap.get("remember_me"));
            try {
                fileService.physicalDeleteExpiredFile(user.getUserId());
            } catch (Exception e){

            }
        }
        return res;
    }
}
